package com.ytb.menus;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import com.ytb.portlet.VideoPlayerPortlet;
import com.ytb.portlet.Option;

/**
 * The parser for the <b>menu.xml</b> document. All the menus are saved in the {@link List} of {@link XmlMenu} object.
 * This class must be executed <b>each time</b> a <b>new</b> video is displayed in the video player.
 * If a video has already been displayed, the parser is not called.
 */
public class XmlMenuParser {
	//here you can change the xml's attribut names
	static final String MENU = "menu";
	static final String HEIGHTVIDEO = "heightVideo";
	static final String WIDTHVIDEO = "widthVideo";
	static final String REFVIDEO = "refVideo";
	static final String URL = "url";
	static final String NAMEVIDEO = "nameVideo";
	static final String KEYFRAME = "keyFrame";
	static final String IDKEYFRAME = "idKeyFrame";
	static final String TIMESTAMP = "timestamp";
	static final String DESCRIPTION = "description";
	static final String CLUSTER = "k";
	static List<com.ytb.categories.XmlCategory> LISTCATEGORIES = com.ytb.categories.XmlCategories.getInstance().getListCategories(); // Contains all the categories of the Singleton XmlCategories 
	static String DESCRIPTOR; //Contains one descriptor of the LISTCATEGORIES


/************************* Parseur *************************/

	/**
	 * Open the <b>menu.xml</b> document and read its content.
	 * @param menuFile
	 * 	The path of XML document.
	 * @param xmlMenu
	 * @param referenceVideo
	 * 	The reference of the wanted video.
	 * @return The {@link XmlKeyFrame} object.
	 * @throws XMLStreamException
	 * @throws IOException
	 */
	public static XmlMenu parse(String menuFile, XmlMenu xmlMenu) {
		XmlMenu xmlM = null;
		XMLInputFactory factory = XMLInputFactory.newInstance();
		InputStream is = null;
		XMLStreamReader reader = null;
		try {
			is = (new URL(menuFile)).openConnection().getInputStream();
			reader = factory.createXMLStreamReader(is);
			xmlM = readXmlMenu(reader, xmlMenu);
		} catch (IOException | XMLStreamException e) {
			e.printStackTrace();
		} finally { // Close the flow
			try {
				reader.close();
				is.close();
			} catch (IOException | XMLStreamException e) {
				e.printStackTrace();
			}
		}
		return xmlM;
	}
	
	/**
	 * Parse the XML document and transforms the menu into the Java objects ({@link XmlKeyFrame}).
	 * @param reader
	 * 	The position of the parser.
	 * @param xmlMenu
	 * @param referenceVideo
	 * 	The reference of the wanted video.
	 * @return The {@link XmlKeyFrame} object.
	 * @throws XMLStreamException
	 * @throws IOException
	 */
	public static XmlMenu readXmlMenu(XMLStreamReader reader, XmlMenu xmlMenu) throws XMLStreamException, IOException 
	{
		String xmlMenuRefVideo = "";
		String xmlMenuUrl = "";
		//int i=0;
		
		int idKeyFrame = 0;
		String timestamp = "";
		String description = "";
		boolean isVideoMere=false;
		List<XmlSubMenu> listXmlSubMenus = null;
		boolean knownDescriptor = false;
		String xmlSubMenuTotalName = "";
		List<XmlCluster> listXmlCluster = null;
		String xmlClulsterSrc = "";
		String tagContent = "";
		//int j=0;
		
System.out.println("new XML : "+xmlMenu.toString());
		while(reader.hasNext())
		{
			int event = reader.next();
			switch(event) 
			{
			case XMLStreamConstants.START_ELEMENT:
				switch(reader.getLocalName()) 
				{
				case MENU:
					if (reader.getAttributeValue(null, REFVIDEO) != null) 
					{
						
						xmlMenuRefVideo = reader.getAttributeValue(null, REFVIDEO);
						xmlMenu.setReferenceVideo(xmlMenuRefVideo);
					} 
					else 
					{
						xmlMenu.setReferenceVideo("");
					}
					if (reader.getAttributeValue(null, URL) != null) 
					{
						xmlMenuUrl = reader.getAttributeValue(null, URL);
					} 
					else 
					{
						isVideoMere=true;
					}
					if (reader.getAttributeValue(null, NAMEVIDEO) != null) 
					{
						xmlMenu.setNameVideo(reader.getAttributeValue(null, NAMEVIDEO));
					} 
					else 
					{
						xmlMenu.setNameVideo("");
					}
					String heightVideoTmp = reader.getAttributeValue(null, HEIGHTVIDEO);
					String widthVideoTmp = reader.getAttributeValue(null, WIDTHVIDEO);
					if (heightVideoTmp != null && !heightVideoTmp.equals("") && widthVideoTmp != null && !widthVideoTmp.equals("")) 
					{
						xmlMenu.setHeightVideo(Integer.parseInt(heightVideoTmp));
						xmlMenu.setWidthVideo(Integer.parseInt(widthVideoTmp));
					} 
					else 
					{
						xmlMenu.setHeightVideo(9);
						xmlMenu.setWidthVideo(16);
					}
					
					xmlMenu.setListKeyFrames(new ArrayList<XmlKeyFrame>()); //Replace the listKeyFrames by a new one
					break;
					
				case KEYFRAME:
					String idKeyFrameTmp = reader.getAttributeValue(null, IDKEYFRAME);
					if (idKeyFrameTmp != null && !idKeyFrameTmp.equals("")) 
					{
						idKeyFrame = Integer.parseInt(idKeyFrameTmp);
					} 
					else 
					{
						idKeyFrame = 0;
					}
					
					timestamp = reader.getAttributeValue(null, TIMESTAMP);
					description = reader.getAttributeValue(null, DESCRIPTION);
					listXmlSubMenus = new ArrayList<XmlSubMenu>();
					break;
				case CLUSTER: //no longuer in use
					if (reader.getAttributeValue(null, REFVIDEO) != null) 
					{
						xmlClulsterSrc = reader.getAttributeValue(null, REFVIDEO);
					} else {
						xmlClulsterSrc = "";
					}
					
					break;
				default: //Search for the XmlDescriptor object corresponding with selected TAG
					if (knownDescriptor == false) {
						for (com.ytb.categories.XmlCategory xmlCategory : LISTCATEGORIES) {
							for (com.ytb.categories.XmlDescriptor xmlDescriptor : xmlCategory.getDescriptors()) {
								if (xmlDescriptor.getName().equals(reader.getLocalName())) 
								{ // We have found the correct XmlDescriptor
									DESCRIPTOR = xmlDescriptor.getName(); // Setup the Descriptor name
									xmlSubMenuTotalName = xmlDescriptor.getTotalName(); // Setup the Descriptor total name
									listXmlCluster = new ArrayList<XmlCluster>();
									knownDescriptor = true;
									
									String adresseVideo;
									String nomVideo;
									nomVideo=xmlMenu.getReferenceVideo()+".mp4";
									
									//TODO
									if (isVideoMere)
									{
										adresseVideo=Option.SERVEUR_ADDRESS + Option.SERVEUR_ADDRESS_FRAGMENTS+idKeyFrame+"/"+DESCRIPTOR+"/";
										listXmlCluster.add(new XmlCluster(idKeyFrame,adresseVideo+nomVideo,Integer.toString(idKeyFrame)));
									}
									else
									{
										adresseVideo=Option.SERVEUR_ADDRESS+xmlMenuUrl+idKeyFrame+"/"+DESCRIPTOR+"/";
										String idUnique = "";
										
										String[] results = xmlMenuUrl.split("/");
										for (String x : results) {
											try { 
										        Integer.parseInt(x); 
										        idUnique += x + "_";
										        System.out
														.println("\n x : " + x);
										    } catch(NumberFormatException e) { 
										    }
										}
												
										idUnique = idUnique + idKeyFrame;
										listXmlCluster.add(new XmlCluster(idKeyFrame,adresseVideo+nomVideo,idUnique));
									}
								}
							}
						} // Is the DESCRIPTOR does not exist in the XmlCategories list, it goes in the "OTHERCATEGORY" category.
						if (knownDescriptor == false) {
							DESCRIPTOR = xmlSubMenuTotalName = reader.getLocalName();
							listXmlCluster = new ArrayList<XmlCluster>();
						}
					}
				}
				break;
				
			case XMLStreamConstants.CHARACTERS:
				tagContent = reader.getText().trim();
				break;
				
			case XMLStreamConstants.END_ELEMENT:
				System.out.print("<");
				switch(reader.getLocalName()) 
				{
				case KEYFRAME:
					xmlMenu.addKeyFrame(new XmlKeyFrame(idKeyFrame, timestamp, VideoPlayerPortlet.ADDRESS + VideoPlayerPortlet.ADDRESS_IMAGE + xmlMenuRefVideo + "_" + idKeyFrame + ".png", description, listXmlSubMenus));
					break;
				case CLUSTER:
					break;
				default: // It should be a DESCRIPTOR
					if (DESCRIPTOR.equals(reader.getLocalName())) {
				System.out.print(DESCRIPTOR);
						listXmlSubMenus.add(new XmlSubMenu(DESCRIPTOR, xmlSubMenuTotalName, listXmlCluster));
						knownDescriptor = false;
					}
				}
				break;
				
			case XMLStreamConstants.START_DOCUMENT:
				break;
			}
		}
		return xmlMenu;
	}
}